package org.mspring.mlog.service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.mspring.mlog.dao.OptionDao;
import org.mspring.mlog.entity.Option;
import org.mspring.mlog.entity.constants.CacheNames;
import org.mspring.platform.cache.Cache;
import org.mspring.platform.cache.CacheManager;
import org.mspring.platform.utils.PropertiesUtils;
import org.mspring.platform.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 *
 * @author Gao Youbo
 * @since 2012-7-23
 */
@Service
public class OptionService {

    private static final Logger log = LoggerFactory.getLogger(OptionService.class);

    private OptionDao optionDao;
    private CacheManager cacheManager;
    private Cache optionCache;

    public static final String OPTION_CACHE_MAP_KEY = "OPTION_CACHE_MAP_KEY"; // 保存所有Option缓存的key
    public static final String DEFAULT_OPTIOINS_KEY = "DEFAULT_OPTIONS_KEY"; // 保存默认配置的缓存KEY
    private static final String DEFAULT_OPTIONS_PROPERTIES = "default_options.properties";

    public String getOption(String key) {
        // 先从缓存中获取
        String value = getOptionCacheValue(key);
        if (StringUtils.isNotBlank(value)) {
            return value;
        }

        // 如果缓存中没有找到，从数据库中查询
        Option option = optionDao.findByName(key);
        if (option == null) { // 如果数据库中没有找到，那么从default_options.properties中查找默认值
            value = getDefaultOptions().get(key);
        } else {
            value = option.getValue();
        }
        // 更新缓存
        setOptionCacheValue(key, value);
        return value;
    }

    public Map<String, String> getOptions() {
        // 先从缓存中查找
        Map<String, String> cachedMap = getOptionCacheMap();
        if (cachedMap != null) {
            return cachedMap;
        }

        // 如果缓存中没有找到
        Map<String, String> map = getDefaultOptions();// 初始化为默认配置
        List<Option> options = optionDao.listAll();
        if (options != null && options.size() > 0) {
            for (Option option : options) {
                map.put(option.getName(), option.getValue());
            }
        }
        // 更新缓存内容
        setOptionCacheMap(map);
        return map;
    }

    @Transactional
    public void setOption(String key, String value) {
        setOption(new Option(key, value));
    }

    @Transactional
    public void setOption(Option option) {
        if (StringUtils.isBlank(option.getName())) {
            log.warn("can't update option, key can't be null");
            return;
        }
        optionDao.merge(option);
        // 更新、新增Option缓存
        setOptionCacheValue(option.getName(), option.getValue());
    }

    @Transactional
    public void setOptions(List<Option> options) {
        for (Option option : options) {
            setOption(option);
        }
    }

    @Transactional
    public void setOptions(Map<String, String> options) {
        for (Map.Entry<String, String> entry : options.entrySet()) {
            setOption(entry.getKey(), entry.getValue());
        }
    }

    /**
     * 从default_options.properties中获取值，这些值都不加入缓存
     *
     * @param key
     * @return
     */
    public String getPropertiesOption(String key) {
        Map<String, String> map = PropertiesUtils.getPropertyMap(DEFAULT_OPTIONS_PROPERTIES);
        String value = map.get(key);
        return value;
    }

    /**
     * 设置default_options.properties中的值
     *
     * @param key
     * @param value
     */
    public void setPropertiesOption(String key, String value) {
        PropertiesUtils.setProperties(key, value, DEFAULT_OPTIONS_PROPERTIES);
    }

    private String getOptionCacheValue(String key) {
        return optionCache.get(key);
    }

    private void setOptionCacheValue(String key, String value) {
        optionCache.set(key, value, Cache.ONE_DAY);
        setOptionCacheMap(null);
    }

    private Map<String, String> getOptionCacheMap() {
        return optionCache.get(OPTION_CACHE_MAP_KEY);
    }

    private void setOptionCacheMap(Map<String, String> map) {
        optionCache.set(OPTION_CACHE_MAP_KEY, map, Cache.ONE_DAY);
    }

    /**
     * 获取默认配置
     *
     * @return
     */
    private Map<String, String> getDefaultOptions() {
        try {
            log.debug("获取默认配置...");
            Map<String, String> cached = optionCache.get(DEFAULT_OPTIOINS_KEY);
            if (cached != null && cached instanceof Map) {
                return cached;
            }
            Map<String, String> map = PropertiesUtils.getPropertyMap(DEFAULT_OPTIONS_PROPERTIES);
            optionCache.set(DEFAULT_OPTIOINS_KEY, map, Cache.ONE_DAY);
            return map;
        } catch (Exception e) {
            log.debug("获取默认配置失败！");
            return new HashMap<>();
        }
    }

    @Autowired
    public void setOptionDao(OptionDao optionDao) {
        this.optionDao = optionDao;
    }

    @Autowired
    public void setCacheManager(CacheManager cacheManager) {
        this.cacheManager = cacheManager;
        this.optionCache = this.cacheManager.getCache(CacheNames.OPTION_CACHE);
    }

}
